﻿/*
   Created 2009 December 16, Randall Maas
   Copyright (c) 2009, Randall Maas
   All rights reserved.

   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:

   Redistributions of source code must retain the above copyright notice, this
   list of conditions and the following disclaimer.

   Redistributions in binary form must reproduce the above copyright notice,
   this list of conditions and the following disclaimer in the documentation
   and/or other materials provided with the distribution.

   Neither the name of Blackwood Designs, LLC nor the names of its contributors
   may be used to endorse or promote products derived from this software without
   specific prior written permission.

   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   THE POSSIBILITY OF SUCH DAMAGE.
*/

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System . Threading;

enum States
{
   Stopped,
   Recording,
   Paused
}


public partial class VideoView : Form
{
   /// <summary>
   /// The state of recording
   /// </summary>
   States          State;

   string LastFileName = null;

   VideoController Ctl = new VideoController();

//   PrevPoints      PrevArea;

   public VideoView()
   {
      InitializeComponent();
      saveFileDialog1 . DefaultExt = "wmv";
      openFileDialog1 . DefaultExt = "wmv";
      // 
      // aVSourcesBindingSource
      // 
      VideoSourcesBindingSource.DataSource = VideoSource . VideoDevices();
      AudioSourcesBindingSource.DataSource = AudioDevices();
      BkgndSourcesBindingSource.DataSource = BackgroundSources();
      Ctl . FlipHorizontal = FlipHorizontal . Checked;
      Ctl . SetSource ((VideoSource)    ChooseVideoSource . SelectedItem);
      Ctl . _AudioSource = (DirectShowNode) ChooseAudioSource . SelectedItem;
      OutSize . SelectedIndex = 1;
      Ctl . BuildPreviewGraph(CamPreview);
      Pause . Enabled = false;
   }

   const string sCamera   = "Camera";
   const string OpenMovie = "Open file.....";

   IEnumerable<string> BackgroundSources()
   {
      yield return sCamera;
      if (null != LastFileName)
        yield return LastFileName;

      yield return OpenMovie;
   }

   IEnumerable<DirectShowNode> AudioDevices()
   {
      foreach (DirectShowNode N in DirectShowNode . AudioDevices())
       yield return N;
      // Offer to use movie audio track
      if (null != Ctl . InFileName && null == Ctl . BkgndBasePict)
        yield return VideoController . _MovieAudio;
   }

   /// <summary>
   /// Handle when the video source selection changes
   /// </summary>
   /// <param name="sender"></param>
   /// <param name="e"></param>
   private void ChooseVideoSource_SelectedIndexChanged(object sender, EventArgs e)
   {
      if (!(sender is ComboBox) || null == Ctl)
        return ;
      Ctl . SetSource((VideoSource) ((ComboBox) sender) . SelectedItem);
      Ctl . BuildPreviewGraph(CamPreview);
   }


   /// <summary>
   /// Handle when the audio source selection changes
   /// </summary>
   /// <param name="sender"></param>
   /// <param name="e"></param>
   private void ChooseAudioSource_SelectedIndexChanged(object sender, EventArgs e)
   {
      if (!(sender is ComboBox) || null == Ctl)
        return ;
      Ctl . SetSource((DirectShowNode) ((ComboBox) sender) . SelectedItem);
   }

   /// <summary>
   /// This is called whenever the background combo box selection changes
   /// </summary>
   /// <param name="sender"></param>
   /// <param name="e"></param>
   private void BackgroundSelection_SelectedIndexChanged(object sender, EventArgs e)
   {
      if (!(sender is ComboBox) || null == Ctl)
        return ;


      // Switch between a movie as the source background
      // or using the camera
      string Name = (string)((ComboBox) sender) . SelectedItem;
      Ctl . InFileName = null;

      if (OpenMovie == Name)
        {
           if (DialogResult . Cancel == openFileDialog1 . ShowDialog(this))
             return ;
           Ctl . InFileName = openFileDialog1 . FileName;
           if (null != Ctl . InFileName)
             {
                LastFileName = Ctl . InFileName;
                // Force reload of the file names
                AudioSourcesBindingSource.DataSource = AudioDevices();
                BkgndSourcesBindingSource.DataSource = BackgroundSources();
                BackgroundSelection . SelectedItem = Ctl . InFileName;
             }
        }
      else if (sCamera == Name)
        ;
      else
       Ctl . InFileName = Name;
   }


   private void button2_Click(object sender, EventArgs e)
   {
      Ctl . ClearPen();
   }

   private void trackBar1_Scroll(object sender, EventArgs e)
   {
      Ctl . Threshold(trackBar1 . Value);
   }


   /// <summary>
   /// The user asked to flip the camera
   /// </summary>
   /// <param name="sender"></param>
   /// <param name="e"></param>
   private void FlipHorizontal_CheckedChanged(object sender, EventArgs e)
   {
      Ctl . FlipHorizontal =FlipHorizontal . Checked;
   }


   /// <summary>
   /// This is called when the record/stop button is pressed.  We'll ask where to save the file
   /// </summary>
   /// <param name="sender"></param>
   /// <param name="e"></param>
   private void Record_Click(object sender, EventArgs e)
   {
      switch(State)
      {
         // --- Start recording ---
         case States . Stopped:
           if (DialogResult . Cancel == saveFileDialog1 . ShowDialog(this))
             return;
           State = States . Recording;
           Record . Text = "Stop";
           Pause . Enabled = true;
           ChooseVideoSource . Enabled = false;
           ChooseAudioSource . Enabled = false;
           OutSize . Enabled = false;
           Ctl . EncProfile = DirectShowNode . Profiles [ OutSize . SelectedIndex ];
           Ctl . TgtWidth = 320 << OutSize . SelectedIndex;

           // magic to start recording;
           Ctl . RebuildGraph(saveFileDialog1 . FileName, CamPreview, panel1);
           break;

         // --- Stop recording ---
         case States . Recording:
         case States . Paused:
           State = States . Stopped;
           Pause . Enabled = false;
           ChooseVideoSource . Enabled = true;
           ChooseAudioSource . Enabled = true;
           Record . Text = "Record";
           OutSize . Enabled = true;

           // stop recording;
           Ctl . Stop ();
           Ctl . BuildPreviewGraph(CamPreview);
           break;
      }
   }


   /// <summary>
   /// This is called when the pause/resume but it clicked on
   /// </summary>
   /// <param name="sender"></param>
   /// <param name="e"></param>
   private void Pause_Click(object sender, EventArgs e)
   {
      switch(State)
      {
         case States . Stopped:
           break;
         case States . Recording:
           State = States . Paused;
           Pause . Text = "Resume";
           // pause recording
           Ctl . Pause();
           break;

         case States . Paused:
           State = States . Recording;
           Pause . Text = "Pause";
           // Resume recording;
           Ctl . Start();
           break;
      }

   }


   /// <summary>
   /// This is called when the video preview area is resized,
   /// so that we can tell the video preview itself to resize.
   /// </summary>
   /// <param name="sender"></param>
   /// <param name="e"></param>
   private void PreviewResized(object sender, EventArgs e)
   {
      Ctl . ResizePreview(panel1);
   }


   /// <summary>
   /// Pop up the property configuration for the camera
   /// </summary>
   /// <param name="sender"></param>
   /// <param name="e"></param>
   private void button1_Click(object sender, EventArgs e)
   {
      Ctl . ConfigVideoSource(Handle);
   }
}
